package com.ww.learn.actors

import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.runBlocking

// 统计相关消息
sealed class StatMessage {
    // 记录一次接口调用（渠道+响应状态）
    data class RecordCall(val channel: String, val status: Int) : StatMessage()

    // 查询当前分钟的统计数据
    data class QueryCurrentMinute(val response: CompletableDeferred<StatData>) : StatMessage()

    // 定时清零
    object ResetMinute : StatMessage()
}

// 统计数据模型
data class StatData(
    val totalCalls: Int = 0,
    val channelCalls: Map<String, Int> = emptyMap(), // 渠道 -> 次数
    val errorCalls: Map<String, Int> = emptyMap() // 状态码 -> 次数，
)

// 实现Actor逻辑
fun CoroutineScope.statisticsActor(): SendChannel<StatMessage> = actor<StatMessage>(
    capacity = 1000 // 消息队列容量（应对突发流量）
) {
    var currentStat = StatData() // 内部状态

    // 循环处理消息
    for (msg in channel) {
        when (msg) {
            is StatMessage.RecordCall -> {
                // 更新总调用次数
                val newTotal = currentStat.totalCalls + 1
                // 更新渠道统计
                val newChannelCalls = currentStat.channelCalls.toMutableMap().apply {
                    this[msg.channel] = (this[msg.channel] ?: 0) + 1
                }
                // 更新错误统计
                val newErrorCalls = if (msg.status !in 200..299) {
                    currentStat.errorCalls.toMutableMap().apply {
                        val statusKey = msg.status.toString()
                        this[statusKey] = (this[statusKey] ?: 0) + 1
                    }
                } else {
                    currentStat.errorCalls
                }
                currentStat = currentStat.copy(
                    totalCalls = newTotal,
                    channelCalls = newChannelCalls,
                    errorCalls = newErrorCalls
                )
            }

            is StatMessage.QueryCurrentMinute -> {
                msg.response.complete(currentStat) // 回传当前统计数据
            }

            is StatMessage.ResetMinute -> {
                currentStat = StatData() // 清零
            }
        }
    }
}

class ProductDetailService(
    private val statActor: SendChannel<StatMessage>
) {
    // 接口调用时记录统计
//    suspend fun getProductDetail(productId: String, channel: String): Product {
//        try {
//            val product = productDao.queryById(productId)
//            statActor.send(StatMessage.RecordCall(channel, 200)) // 记录成功
//            return product
//        } catch (e: Exception) {
//            statActor.send(StatMessage.RecordCall(channel, 500)) // 记录异常
//            throw e
//        }
//    }

    // 定时任务：每分钟清零
//    @Scheduled(cron = "0 * * * * ?")
    fun resetMinuteStat() {
        runBlocking {
            statActor.send(StatMessage.ResetMinute)
        }
    }

    // 监控接口：查询当前统计
    suspend fun getCurrentStat(): StatData {
        val response = CompletableDeferred<StatData>()
        statActor.send(StatMessage.QueryCurrentMinute(response))
        return response.await()
    }
}